﻿using System;
using System.Collections.Generic;
using System.Linq;
//using System.Net;
using System.Device.Location;
using System.Windows;
//using System.Windows.Controls;
//using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
//using System.Windows.Media.Animation;
//using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;

using BEO.BingSearchService;
using Microsoft.Phone.Controls.Maps;
using BEO.GeocodeService;

namespace BEO
{
    public partial class Add : PhoneApplicationPage
    {
        #region Members

        private GeoCoordinateWatcher geoCoordinateWatcher;
        private GeoPosition<GeoCoordinate> geoPosition;
        private Pushpin searchPushPin;
        private const string BingApiAppId = "FD2F431149BED7CA1E67A284A968352E457D832F";

        #endregion

        #region Constructors

        public Add()
        {
            InitializeComponent();

            // set current location
            geoCoordinateWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
            searchPushPin = new Pushpin();
            searchPushPin.Location = new GeoCoordinate(-81.518272, -136.054687);
            mSearch.Children.Add(searchPushPin);
        }

        #endregion

        #region Event Handlers

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            // reset all input
            ResetInput();
        }

        private void MyLocation_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            // update position
            geoPosition = e.Position;

            // set location on map
            mSearch.Center = geoPosition.Location;

            // stop task and unregister event handler
            geoCoordinateWatcher.Stop();
            geoCoordinateWatcher.PositionChanged -= MyLocation_PositionChanged;
        }

        private void Reset_Click(object sender, RoutedEventArgs e)
        {
            ResetInput();
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            (App.Current as App).Errands.Add(
                new Errand()
                {
                    Title = tbName.Text,
                    Description = tbDescription.Text,
                    Address = tbAddress.Text,
                    Latitude = geoPosition.Location.Latitude,
                    Longitude = geoPosition.Location.Longitude,
                    Time = (int)sTime.Value
                }
            );

            // navigate
            this.NavigationService.GoBack();
        }

        private void Search_Click(object sender, RoutedEventArgs e)
        {
            string searchTerm = tbSearch.Text;

            if (!String.IsNullOrEmpty(searchTerm) && !searchTerm.Equals("Search Current Location"))
            {
                SearchMappingForSearchTerm(searchTerm);
            }

        }

        private void SearchMappingForSearchTerm(string searchTerm)
        {
            // http://blogs.msdn.com/b/silverlightws/archive/2010/03/17/two-samples-from-today-s-mix-2010-talk.aspx
            SearchRequest searchRequest = new SearchRequest
            {
                LatitudeSpecified = true,
                Latitude = geoPosition.Location.Latitude,
                LongitudeSpecified = true,
                Longitude = geoPosition.Location.Longitude,
                AppId = BingApiAppId,
                Query = searchTerm,
                Sources = new SourceType[] { SourceType.Phonebook },
                Phonebook = new PhonebookRequest
                {
                    SortBy = PhonebookSortOption.Distance
                }
            };

            BingPortTypeClient client = new BingPortTypeClient();
            client.SearchCompleted +=
                new EventHandler<SearchCompletedEventArgs>(SearchClient_SearchCompleted);

            client.SearchAsync(searchRequest);
        }

        void SearchClient_SearchCompleted(object sender, SearchCompletedEventArgs e)
        {
            PhonebookResponse response = e.Result.Phonebook;
            if (e.Error == null && response != null &&
                response.Results.Count<PhonebookResult>() > 0)
            {
                List<PhonebookResult> closestEntries = response.Results.ToList<PhonebookResult>();

                Pushpin entryPin = null;
                foreach (PhonebookResult result in closestEntries)
                {
                    entryPin = new Pushpin();
                    entryPin.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(pushPin_Tapped);
                    entryPin.Location = new GeoCoordinate(result.Latitude, result.Longitude);
                    mSearch.Children.Add(entryPin);
                }

                GeoCoordinate geoCoord = new GeoCoordinate(closestEntries[0].Latitude, closestEntries[0].Longitude);
                mSearch.Center = geoCoord;
            }
            else
            {
                MessageBox.Show("Error no search results.");
            }
        }

        private void Search_GotFocus(object sender, RoutedEventArgs e)
        {
            if (tbSearch.Text.Equals("Search My Location"))
            {
                tbSearch.Text = string.Empty;
            }
        }

        private void Search_LostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(tbSearch.Text))
            {
                tbSearch.Text = "Search My Location";
            }
        }

        private void Name_GotFocus(object sender, RoutedEventArgs e)
        {
            if (tbName.Text.Equals("Name"))
            {
                tbName.Text = string.Empty;
            }
        }

        private void Name_LostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(tbName.Text))
            {
                tbName.Text = "Name";
            }
        }

        private void Description_GotFocus(object sender, RoutedEventArgs e)
        {
            if (tbDescription.Text.Equals("Description"))
            {
                tbDescription.Text = string.Empty;
            }
        }

        private void Description_LostFocus(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(tbDescription.Text))
            {
                tbDescription.Text = "Description";
            }
        }

        private void Time_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (tbTime != null)
            {
                tbTime.Text = string.Format("{0}m", ((int)e.NewValue).ToString());
            }
        }

        private void mSearch_MapPan(object sender, MapDragEventArgs e)
        {
            lookupAddressFromMapPoint(mSearch.Center);
        }

        private void lookupAddressFromMapPoint(GeoCoordinate location)
        {
            ReverseGeocodeRequest locationRequest = new ReverseGeocodeRequest();
            locationRequest.Credentials = new Credentials();
            locationRequest.Credentials.ApplicationId = "ApYlhArPQQbmi_7yAwx_kvdreL-5xDeTbxfvdjcq8g_5Dg4JBZEinwhimEo72QZV";
            locationRequest.Location = location;

            GeocodeServiceClient geocodeClient = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            geocodeClient.ReverseGeocodeCompleted +=
                new EventHandler<ReverseGeocodeCompletedEventArgs>(geocodeService_ReverseGeocodeCompleted);

            geocodeClient.ReverseGeocodeAsync(locationRequest);
        }

        private void geocodeService_ReverseGeocodeCompleted(object sender, ReverseGeocodeCompletedEventArgs e)
        {
            try
            {
                if (e.Result.Results[0] != null)
                {
                    //Check for multiple other results (ie from searching)
                    if (mSearch.Children.Count >= 2)
                    {
                        mSearch.Children.Clear();
                        mSearch.Children.Add(searchPushPin);
                    }

                    GeocodeResult result = e.Result.Results[0];
                    //tbAddress.Text = string.Format("{0}\n{1}", result.DisplayName, result.Address.FormattedAddress);

                    SetPinnedAddressInformation(result);

                    searchPushPin.Location = mSearch.Center;
                }
            }
            catch (NullReferenceException noConnection)
            {
                System.Console.Write(noConnection.ToString());
            }
        }

        private void SetPinnedAddressInformation(GeocodeResult result = null)
        {
            bAddress.Background = new SolidColorBrush(new Color() { A = (result == null) ? (byte)0 : (byte)200 });
            tbAddress.Text = (result == null) ? string.Empty : string.Format("{0}", result.Address.FormattedAddress);
        }

        private void pushPin_Tapped(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            lookupAddressFromMapPoint(((Pushpin)sender).Location);
            mSearch.Center = ((Pushpin)sender).Location;
        }

        private void TextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            // if the enter key is pressed
            if (e.Key == Key.Enter)
            {
                // focus page
                this.Focus();
            }
        }

        private void Search_KeyUp(object sender, KeyEventArgs e)
        {
            // if the enter key is pressed
            if (e.Key == Key.Enter)
            {
                // focus page
                Search_Click(sender, new RoutedEventArgs());
            }
        }

        #endregion

        private void ResetInput()
        {
            // set search text
            tbSearch.Text = "Search My Location";
            // set name text
            tbName.Text = "Name";
            // set description text
            tbDescription.Text = "Description";
            // set slider value
            sTime.Value = 15;
            // set address information
            SetPinnedAddressInformation();

            // register coordinate watching handler and start it to get current location
            geoCoordinateWatcher.PositionChanged += MyLocation_PositionChanged;
            geoCoordinateWatcher.Start();

        }
    }
}